#include "ioseq.h"
#include "../kernel/debug.h"
#include "../thread/sync.h"
#include "../lib/string.h"
#include "../lib/kernel/print.h"
#include "../lib/stdint.h"
void io_seq_init(struct io_seq* ioSeq)
{
    lock_init(&ioSeq->io_lock);
    ioSeq->limit = 0;
    ioSeq->pos = 0;
    ioSeq->consumer = NULL;
    ioSeq->provider = NULL;
}

static uint8_t next_pos(uint8_t pos)
{
    return (pos + 1) % IO_SEQ_BUF_SIZE;
}

static iosqe_wait(struct io_seq* ioSeq)
{
     ioSeq->consumer = current_thread();
     thread_block(TASK_BLOCKED);
}

static iosqe_wakeup(struct task_struct** waiter)
{
    thread_unblock(*waiter);
    *waiter = NULL;
}


uint8_t io_seq_get(struct io_seq* ioSeq)
{
    while( io_seq_empty(ioSeq)){
        lock_acquire(&ioSeq->io_lock);
        if(  io_seq_empty(ioSeq) ){
            iosqe_wait(ioSeq);
        }
        
        lock_release(&ioSeq->io_lock);
    }
    lock_acquire(&ioSeq->io_lock);
    uint8_t val = ioSeq->codeBuf[ioSeq->pos];
    ioSeq->pos = next_pos(ioSeq->pos);
    lock_release(&ioSeq->io_lock);
    return val;
}


void io_seq_add(struct io_seq* ioSeq,uint8_t val)
{
    ioSeq->provider = current_thread();
    ioSeq->codeBuf[ ioSeq->limit] = val;
 
    /**
     * 如果，环形队列是满的，那么pos（起始位置）需要推进一个，
     * 即，丢弃掉队列中最老的一个数据
    */
    
    if( io_seq_full(ioSeq) ){
        lock_acquire(&ioSeq->io_lock);
         if( io_seq_full(ioSeq) ){
            ioSeq->pos  = (ioSeq->pos + 1) % IO_SEQ_BUF_SIZE;
         }
        lock_release(&ioSeq->io_lock);
    }
    ioSeq->limit  = next_pos(ioSeq->limit);
   
    if(ioSeq->consumer != NULL){
        iosqe_wakeup(&ioSeq->consumer);
    }
   
}
 

bool io_seq_empty(struct io_seq* ioSeq)
{
    return ioSeq->limit == ioSeq->pos;
}



bool io_seq_full(struct io_seq* ioSeq)
{
    return ioSeq->pos   == next_pos(ioSeq->limit );
}